package model;

/**
 * The ComponentState class contains the master of this state as well as the common refresh method.
 * 
 * @author hfi411pi
 */
public abstract class ComponentState {
	private final ComponentCommon master;
	
	public ComponentCommon getMaster() {
		return master;
	}
	
	/**
	 * Constructor of ComponentState
	 * @param master is the ComponentCommon this state is the state of.
	 */
	protected ComponentState(final ComponentCommon master) {
		this.master = master;
	}

	
	/**
	 * Provides the MaterialList of the master component of this state.
	 * If the MaterialList is not cached the newly calculated MaterialList will
	 * be cached before the return.
	 * If the MaterialList is cached the cached MaterialList will
	 * be provided.
	 * @return the cached MaterialList.
	 */
	public abstract MaterialList getMaterialList();
	
	/**
	 * Provides the overall price of the master component of this state.
	 * If the overall price is not cached the newly calculated overall price will
	 * be cached before the return.
	 * If the overall price is cached the cached overall price will
	 * be provided.
	 * @return the cached overall price.
	 */
	public abstract int getOverallPrice();


	/**
	 * Refreshes this state with an event.
	 * Notifies all Observers of this state's master with the provided event.
	 * @param event is the event to handle.
	 */
	public void refresh(final Event event) {
		event.accept(new EventVisitor() {
			
			@Override
			public void handleStuctureChangedEvent(
					final StructureChangedEvent structureChangedEvent) {
				ComponentState.this.handleStructureChangedEvent(structureChangedEvent);
				ComponentState.this.getMaster().notifyObserver(structureChangedEvent);
			}
			
			@Override
			public void handlePriceChangedEvent(final PriceChangedEvent priceChangedEvent) {
				ComponentState.this.handlePriceChangedEvent(priceChangedEvent);
				ComponentState.this.getMaster().notifyObserver(priceChangedEvent);
				
			}
		});
	}

	/**
	 * Handles the price changed event.
	 * @param priceChangedEvent is the event to handle.
	 */
	protected abstract void handlePriceChangedEvent(final PriceChangedEvent priceChangedEvent);
	
	/**
	 * Handles the structure changed event
	 * @param structureChangedEvent is the event to handle.
	 */
	protected abstract void handleStructureChangedEvent(final StructureChangedEvent structureChangedEvent);
}
